package taxonomy

import exquery.util.WildCardUtil
import org.apache.log4j.Logger
import exquery.util.CommonUtil

class NCBITaxonomyService {

    static transactional = true
    WildCardUtil wildCard = WildCardUtil.getInstance();
    Logger gLogger = Logger.getLogger(NCBITaxonomyService.class)

    /**
     * Search for Taxonomy By TaxonomyName
     * @param taxonomyName
     * @return
     */
    def searchTaxonomyByTaxonomyName(String taxonomyName){
      def taxonomyNodesList = []
      if(taxonomyName!=null && taxonomyName.toString().trim().length()>0){
        taxonomyNodesList = TaxonomyNames.executeQuery("select distinct tn.tax from taxonomy.TaxonomyNames tn  where upper(tn.nameTxt) = :nameTxt",["nameTxt":taxonomyName.toUpperCase()])
      }

      return taxonomyNodesList
    }

    /**
     * Search for Taxonomy By TaxonomyName with like option
     * @param taxonomyName
     * @return
     */
    def searchTaxonomyByTaxonomyNameWithWildCards(String taxonomyName, Map params = [:],def wildCards = true){

      if ( taxonomyName instanceof String && wildCards) {
          taxonomyName = wildCard.convertToLikeWildCard(taxonomyName)
      }

      def uniqueSxSpeciesIds = params?.uniqueSxSpeciesIds

      gLogger.info "taxonomyName:: ${taxonomyName}"
      gLogger.info "uniqueSxSpeciesIds:: ${uniqueSxSpeciesIds}"
      def taxonomyNodeList

      if(uniqueSxSpeciesIds!=null && uniqueSxSpeciesIds.size() > 0){
        taxonomyNodeList = TaxonomyNames.executeQuery("select distinct tn.tax from taxonomy.TaxonomyNames tn  where upper(tn.nameTxt) like :nameTxt and tn.tax.id in (:uniqueSxSpeciesIds) ",["nameTxt":taxonomyName.toUpperCase(),"uniqueSxSpeciesIds":uniqueSxSpeciesIds],params)
      }else{
        taxonomyNodeList = TaxonomyNames.executeQuery("select distinct tn.tax from taxonomy.TaxonomyNames tn  where upper(tn.nameTxt) like :nameTxt",["nameTxt":taxonomyName.toUpperCase()],params)
      }

      gLogger.info "taxonomyNodeList:: ${taxonomyNodeList}"
      gLogger.info "taxonomyNodeList.size:: ${taxonomyNodeList?.size()}"
      return taxonomyNodeList?.sort {it.id}
    }

    /**
     * Search for TaxonomyId By TaxonomyName
     * @param taxonomyName
     * @return
     */
    Collection<Long> searchTaxonomyIdByTaxonomyName(String taxonomyName){
        def taxonomyNodeObj = searchTaxonomyByTaxonomyName(taxonomyName)
        Collection<Long> taxonomyIds
        if(taxonomyNodeObj!=null ){
            taxonomyIds = new ArrayList<Long>()
            if(taxonomyNodeObj instanceof Collection ){
                taxonomyNodeObj.each {TaxonomyNodes taxonomyNode->
                    taxonomyIds.add(taxonomyNode.id)
                }
            }
        }

        return taxonomyIds
    }

    /**
     * Get All Names for a Taxonomy By TaxonomyName
     * @param taxonomyName
     * @return
     */
    def getAllNamesByTaxonomyName(String taxonomyName){
      //println "taxonomyName :: ${taxonomyName}"
      def taxIds = searchTaxonomyIdByTaxonomyName(taxonomyName)
      //println "taxIds :: ${taxIds}"
      def taxNames = getAllNamesByTaxonomyIds(taxIds)

      return taxNames
    }

    /**
     * Get All Names for a Taxonomy By TaxonomyIds
     * @param taxonomyIds
     * @return
     */
    def getAllNamesByTaxonomyIds(def taxonomyIds){
      def taxNames = []
      //println("taxonomyIds :: ${taxonomyIds}")
      if(taxonomyIds!=null){

        if(taxonomyIds instanceof Collection || taxonomyIds instanceof Long[]){
            taxonomyIds.each {taxonomyId->
                TaxonomyNodes taxNode = TaxonomyNodes.findById(taxonomyId)
                if(taxNode!=null){
                  def taxonomyNamesSet = taxNode.taxonomyNamesSet
                  taxonomyNamesSet?.each {taxonomyName->
                    taxNames.add(taxonomyName.getNameTxt())
                  }
                }
            }
        }else if(taxonomyIds instanceof Long){
            TaxonomyNodes taxNode = TaxonomyNodes.findById(taxonomyIds)
            if(taxNode!=null){
              def taxonomyNamesSet = taxNode.taxonomyNamesSet
              taxonomyNamesSet?.each {taxonomyName->
                taxNames.add(taxonomyName.getNameTxt())
              }
            }
        }

        // prepare unique list
        if(taxNames!=null){
           taxNames = CommonUtil.getInstance().getDistinctList(taxNames)
        }


      }
      return taxNames
    }

    /**
     * to get taxonomy scientific name for the taxonomy Id  
     * @param taxonomyId
     * @return
     */
    def getTaxonomyScientificName(Long taxonomyId){
        def scientificName
        if(taxonomyId!=null){
            TaxonomyNodes taxNode = TaxonomyNodes.findById(taxonomyId)

            if(taxNode!=null){
                TaxonomyNames taxName = TaxonomyNames.findByTaxAndNameClass(taxNode,"scientific name")
                if(taxName!=null){
                    scientificName = taxName?.nameTxt
                }
            }
        }

        return scientificName
    }

    /**
     * to get the synonyms for the taxonomy Id  
     * @param taxonomyId
     * @return
     */
    def getTaxonomySynonyms(Long taxonomyId){
        def taxNames = []
        TaxonomyNodes taxNode = TaxonomyNodes.findById(taxonomyId)

        def taxonomyNamesSet = TaxonomyNames.findAllByTaxAndNameClassNotEqual(taxNode,"scientific name")
        //gLogger.info "taxonomyNamesSet :: ${taxonomyNamesSet}"

        taxonomyNamesSet?.each {taxonomyName->
          taxNames.add(taxonomyName.getNameTxt())
        }
        return taxNames
    }

    /**
     * get taxonomy division ids by ncbiIds
     * @param taxIds
     * @return Collection<TaxonomyDivisions>
     */
    def getUniqueDivisionsByNCBIIds(def taxIds){
        Collection<TaxonomyDivisions> taxonomyDivisionList = null

        if(taxIds!=null){
            if(taxIds instanceof Collection){
                taxonomyDivisionList = TaxonomyDivisions.executeQuery("select distinct tn.division from taxonomy.TaxonomyNodes tn  where tn.id in (:taxIds)",["taxIds":taxIds])
            }else if(taxIds instanceof Long[] || taxIds instanceof long[]){
                taxonomyDivisionList = TaxonomyDivisions.executeQuery("select distinct tn.division from taxonomy.TaxonomyNodes tn  where tn.id in (:taxIds)",["taxIds":taxIds])
            }else if(taxIds instanceof Long){
                taxonomyDivisionList = TaxonomyDivisions.executeQuery("select distinct tn.division from taxonomy.TaxonomyNodes tn  where tn.id = :taxIds",["taxIds":taxIds])
            }
        }

        return taxonomyDivisionList
    }

}
